#include "separated_weighted_resampler.h"
#include "pair_sampler_sorted.h"
#include <iostream>

bool separated_weighted_resampler::resample_problem(boosting_problem & prob, double * d_t, int & argc, char **& argv, boosting_problem & selected_prob) {
	if(argc < 2) {
		cout << "arguments not sufficient!" << endl;
		return false;
	}

	int size = atoi(argv[0]);
	double alpha = atof(argv[1]);
	int p_size = (int) (alpha * size);
	int n_size = size - p_size;

	int l = prob.l;

	selected_prob.dim = prob.dim;
	selected_prob.y = new double[size];
	selected_prob.x = new boosting_node *[size];

	int pl = count_samples(prob, 1);
	int nl = count_samples(prob, -1);

	double * py = new double[pl];
	double * ny = new double[nl];
	boosting_node ** px = new boosting_node*[pl];
	boosting_node ** nx = new boosting_node*[nl];
	double * pd = new double[pl];
	double * nd = new double[nl];

	get_samples(prob, d_t, py, px, pd, 1);
	get_samples(prob, d_t, ny, nx, nd, -1);

	normalize(pd, pl);
	normalize(nd, nl);

	p_size = weighted_resample(py, px, pl, pd, p_size, selected_prob.y, selected_prob.x);
	n_size = weighted_resample(ny, nx, nl, nd, n_size, selected_prob.y + p_size, selected_prob.x + p_size);
	selected_prob.l = p_size + n_size;

	argc -= 2;
	argv += 2;

	delete [] py;
	delete [] ny;
	delete [] px;
	delete [] nx;
	delete [] pd;
	delete [] nd;

	return true;
}

int separated_weighted_resampler::count_samples(boosting_problem & prob, double label) {
	int count = 0;
	for(int i = 0; i < prob.l; i++) {
		if(prob.y[i] == label) {
			count ++;
		}
	}
	return count;
}

void separated_weighted_resampler::get_samples(boosting_problem & prob, double * d, double * y, boosting_node ** x, double * d_t, double label) {
	int index = 0;
	for(int i = 0; i < prob.l; i++) {
		if(prob.y[i] == label) {
			y[index] = prob.y[i];
			x[index] = prob.x[i];
			d_t[index] = d[i];
			index++;
		}
	}
}

void separated_weighted_resampler::normalize(double * d, int l) {
	double sum = 0;
	for(int i = 0; i < l; i++) {
		sum += d[i];
	}

	for(int i = 0; i < l; i++) {
		d[i] /= sum;
	}
}

pair_sampler_sorted * separated_weighted_resampler::get_pair_sampler_sorted() {
	return weighted_resampler::get_pair_sampler_sorted();
}

pair_sampler_sorted * separated_weighted_once_resampler::get_pair_sampler_sorted() {
	return new pair_sampler_sorted_once();
}
